function BI() {}

//NOTE: these xmls use the default values
BI.chartsXml = [];
BI.chartsXml['pie'] = 
	'<pieConfiguration>' +
		'<title>My Pie Chart</title><perColumn />' +
		'<lowerLimit /><use3D /><backgroundColor id="" />' +
	'</pieConfiguration>';

BI.chartsXml['bar'] = 
	'<barConfiguration>' +
		'<title>My Bar Chart</title><perColumn /><categoryLabel /><valueLabel />' +
		'<vertical>true</vertical><stacked /><includeLegend /><legendFontSize />' +
		'<base /><backgroundColor id="" />' +
	'</barConfiguration>';

BI.chartsXml['line'] = 
	'<lineConfiguration>' +
		/*<perColumn /> <base /> <itemLabelsVisible /> */
		'<title>My Line Chart</title><categoryLabel /><valueLabel />' +
		'<vertical>true</vertical><stacked /><includeLegend>true</includeLegend><legendFontSize />' +
		'<backgroundColor id="" /><manyCharts/>' +
	'</lineConfiguration>';



BI.action = function(obj, url, value) {
	if (value) {
		var data = value.split(',');
		obj.options[0].selected = true;
		url = BI.removeParam(url, 'noheader');
		jrapid.form({
			entity: data[0], 
			defaultsetparams: 'Table/' + encodeURIComponent(url), 
			defaultset: data[1],
			module: 'Main',
			target: 'window'
		});	
	}
};

BI.openForm = function(id, entity) {
	jrapid.form({entity: entity, id: id, module: 'Main'});
};

BI.include = function(url, canvas) {
	if (!canvas) {
		canvas = document.createElement('div');
		document.body.appendChild(canvas);
	}
	var o = new XMLHttpRequest();	
	o.open('GET', url, true);
	o.onreadystatechange = function() {
		if (o.readyState == 4) { 
			canvas.innerHTML = o.responseText; 
		}
	};
	o.send('');
};

BI.open = function(url, target, params) {
	var div = document.createElement('div');   //div.style.padding = '10px';
	document.body.appendChild(div);
	var o = new XMLHttpRequest();	
	o.open('GET', url, true);
	o.onreadystatechange = function() {
		if (o.readyState == 4) { 
			div.id = 'bi' + new Date().getTime();
			div.innerHTML = o.responseText; 
			div.style.position = 'absolute';
			div.style.top = '0px';
			var w = div.offsetWidth;
			var h = div.offsetHeight;
			var win = jrapid.wrap(application.openWindow('Table', div, null, null, null, null, true));
			var size = document.documentElement.clientHeight-div.getBoundingClientRect().top-52;
			if (size < h) { 
				div.parentNode.style.overflowY = 'scroll'; 
				div.parentNode.style.height = size + 'px';
			}
			h = Math.min(h, size);
			win.resizeTo(w, h, true);
			div.style.width = '100%';
			div.style.position = '';			
		}
	};
	o.send('');
};

BI.chartDashboard = function(obj, id) {
	var img = document.getElementById('img' + id);
	var url = BI.removeParam( BI.removeParam( img.src, 'width'), 'height' );
	jrapid.form({
        entity: 'Chart',
        defaultset: 'forUrl',
        module: 'Main',
        defaultsetparams: encodeURIComponent(url),
        target: 'window'
	});
};

BI.chartConfigure = function(obj, type, id) {
	var name = type;
	type = type.charAt(0).toUpperCase() + type.substring(1);
    var sourcePrototype = jrapid.createSource();
    sourcePrototype.outerNode.id = 'source' + new Date().getTime();
    document.body.appendChild(sourcePrototype.outerNode);
    //sourcePrototype.outerNode.zIndex = 1000;
	sourcePrototype.setUrl('../jrapid-runtime/bi/' + type +  'Configuration_form.html');
	var container = jrapid.wrap(obj).getContainer();
	var img = document.getElementById('img' + id);
	
    sourcePrototype.open(
    	function() {
	  	  	var w = application.openWindow(type, container.getElementById('windowcontainer').outerNode);
	  	  	w.setAttribute('onclosewindow', 'jrapid.close("' + sourcePrototype.outerNode.id + '");');
    		
		    var xml = container.getElementById('xml');
		    xml.setXml( BI.chartsXml[name] );  // chart template (hardcoded in this file)
		    
		    // update xml TEMPLATE with previous chart config (stored on image's src)
		    var xmlWithValues = BI.initChartConfigure( xml.getXmlDocument(), img );
		    xml.setXml( xmlWithValues.xml );
		    
		    var xsl = container.getElementById('xsl');
		    xsl.refresh();  	
		    var submit = container.getElementById('submit');
		    submit.outerNode.onclick = function() {
		    	var form = container.getElementById('form').outerNode;
		    	var s = '';
		    	// get form values to build the new image src.
		    	for (var i=0, c=form.elements, n = c.length; i<n; i++) {
		    		if (c[i].id.indexOf(name) == 0) {
		    			var paramName = c[i].id.substring( (name+'configuration').length + 1 ); 
		    			if (c[i].type == 'checkbox'){
		    				s += '&' + paramName + '=' + c[i].checked;
		    			} else if (c[i].value.length) {
		    				s += '&' + paramName + '=' + c[i].value;
		    			}
			    	}
		    	}
		    	if (!img.basesrc) {
		    		img.basesrc = img.src;
		    	}
		    	img.querysrc = s;
		    	
		    	img.src = img.basesrc + img.querysrc + '&width=' + img.width + '&height=' + img.height; 
		    	
		    	// close the CONFIGURE jrapid-window
		    	sourcePrototype.outerNode.parentNode.removeChild(sourcePrototype.outerNode);
		    	
		    } // end of submit's onclick handler
    	} // end of open callback function
    );
};

// get values from the IMG src, and pass them to the jrapid-form's xml
BI.initChartConfigure = function( xmlDoc, img ){
	var imgUrl = img.src;
	var chartParams = xmlDoc.selectNodes( "/*/*" );
	
	// iterate over chart params, and see if image has value/s for it.
	for( var i=0, q=chartParams.length; i < q; i ++ ){
		var chartParam = chartParams[i].nodeName;
		var imgValuesForParam = BI.paramValues( img.src, chartParam );
		if (imgValuesForParam.length > 0) {
			var chartParamNode = xmlDoc.selectNodes( "//" + chartParam );
			var newValue = decodeURIComponent( imgValuesForParam[0] );
			
			// replace text content with img's src value 
			if (chartParamNode[0].childNodes.length > 0) {
				chartParamNode[0].removeChild( chartParamNode[0].childNodes[0])
			}
			chartParamNode[0].appendChild( xmlDoc.createTextNode( newValue ) );
			
			// TODO: and if multiple values??
		}
	}
	return xmlDoc;
}



BI.openImage = function(url, target, type) {
	//window.open(url, target, params);
	var id = new Date().getTime();
	var div = document.createElement('div');
	var img = document.createElement('img');
	var conf = document.createElement('div');
	conf.innerHTML = 
		'<a href="#" onclick="BI.chartConfigure(this, \'' + type + '\', ' + id + ');">Configure</a>' +
		'&nbsp;&nbsp;' +
		'<a href="#" onclick="BI.chartDashboard(this, ' + id + ');">To dashboard</a>';
	img.basesrc = img.src = url;
	img.id = 'img' + id;
	div.appendChild(conf);
	div.appendChild(img);
	document.body.appendChild(div);
	var win = application.openWindow('Chart', div);	
	win.id = 'win' + id;
	win.setAttribute('onresizewindow', 'BI.resizeChart("' + id + '")');
};

BI.resizeChart = function(id) {
	var img = document.getElementById('img' + id);
	// TODO: show LOADING img...
	img.style.display = 'none';
	var rect = document.getElementById('win' + id).getBoundingClientRect();
	
	var imgQueryParams = img.querysrc ? img.querysrc : "";
	img.src = img.basesrc + imgQueryParams + '&width=' + rect.width + '&height=' + rect.height;
	img.style.display = '';
	img.width = rect.width;
	img.height = rect.height;
};

BI.exclude = function(obj, event, dimension) {
	//var url = obj.parentNode.parentNode.parentNode.parentNode.getAttribute('url');
	var url = BI.findCanvasDivUrl( obj ); 
	BI.refresh( obj, url.replace(new RegExp('(,?)' + dimension), '') );
};


BI.order = function(obj, event, dimension, id) {
	if (event.ctrlKey) {
		var th = obj.parentNode;
		var tbody = th.parentNode.parentNode.parentNode.tBodies[0];
		var cell = th.cellIndex;
		
		var total = 0;
		for (var i=0; i < tbody.children.length; i++) {
			if (tbody.children[i].children.length > cell && tbody.children[i].children[cell].children.length) {
				var a = parseFloat(tbody.children[i].children[cell].children[0].innerHTML);
				total += isNaN(a) ? 0 : a;
			}
		}
		
		for (var i=0; i < tbody.children.length; i++) {
			if (tbody.children[i].children.length > cell && tbody.children[i].children[cell].children.length) {
				var a = parseFloat(tbody.children[i].children[cell].children[0].innerHTML);
				tbody.children[i].children[cell].children[0].innerHTML = parseInt(a/total * 100) + '%';
			}
		}
		return;
	}
	//var url = obj.parentNode.parentNode.parentNode.parentNode.parentNode.getAttribute('url');
	var url = BI.findCanvasDivUrl( obj );
	
	// we can sort by Ids or by names/strings
	var orderValue = dimension + ':' + (isNumber(id) ? id : "\"" + encodeURIComponent( id ) + "\"" );
	BI.refresh( obj, BI.addParam(url, 'order', orderValue) );
};

function isNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}



BI.swap = function(obj, event, dimension) {
	//var url = obj.parentNode.parentNode.parentNode.parentNode.getAttribute('url');
	var url = BI.findCanvasDivUrl( obj ); 
	if (!BI.swapOne(obj, dimension, url, 'rows')) {
		BI.swapOne(obj, dimension, url, 'columns');	
	}
}		
	
BI.swapOne = function(obj, dimension, url, type) {
	var v = BI.paramValues(url, type);
	for (var i=0; i < v.length; i++) {
		if (v[i] == dimension) {
			var aux = v[i-1];
			v[i-1] = v[i];
			v[i] = aux;
			url = BI.addParam(url, type, v.join(','));
			BI.refresh(obj, url);
			return true;
		}
	}
	return false;
}

BI.rotate = function(obj, event, dimension) {
	//var url = obj.parentNode.parentNode.parentNode.parentNode.getAttribute('url');
	var url = BI.findCanvasDivUrl( obj ); 
	var rows = BI.paramValues(url, 'rows');
	var columns = BI.paramValues(url, 'columns');
	
	for (var i=0; i < rows.length; i++) {
		if (rows[i] == dimension) {
			rows.splice(i, 1);
			columns[columns.length] = dimension;
			url = BI.addParam(url, 'rows', rows.join(','));
			url = BI.addParam(url, 'columns', columns.join(','));
			BI.refresh(obj, url);
			return;
		}
	}
	
	for (var i=0; i < columns.length; i++) {
		if (columns[i] == dimension) {
			columns.splice(i, 1);
			rows[rows.length] = dimension;
			url = BI.addParam(url, 'rows', rows.join(','));
			url = BI.addParam(url, 'columns', columns.join(','));
			BI.refresh(obj, url);
			return;
		}
	}
}

BI.getUrl = function(obj) {
	return BI.findCanvasDivUrl(obj);
	/*
	//alert( ".getUrl()" );
	var c = obj.parentNode.parentNode.parentNode.parentNode;
	c = c.children[c.children.length-1];
	if (c.children && c.children.length && c.children[0].tagName.toLowerCase() == 'div') {
		return c.children[0].getAttribute('url');	
	}
	return c.getAttribute('url');
	*/	
};

BI.table = function(obj, event, columnCount, rowCount) {

	var thead = obj.parentNode.parentNode.parentNode.parentNode.children[1];
	//var url = thead.parentNode.parentNode.getAttribute('url');
	var url = BI.findCanvasDivUrl( obj );
	var n = thead.children[ columnCount-1 ].children[ obj.parentNode.cellIndex ];
	var names = n.getAttribute('keyname').split('#');
	var keys = n.getAttribute('key').split('#');
	for (var i=0; i < names.length; i++) {
		url = BI.addParam(url, names[i], keys[i]);
	}
	
	for (var i=0; i < rowCount; i++) {
		var n = obj.parentNode.parentNode.children[i];
		url = BI.addParam(url, n.getAttribute('keyname'), n.getAttribute('key'));
	}
	BI.open( 
		BI.addParam( BI.removeParam(url, 'noheader'), 'table', 'true'), 
		'_blank', 
		'width=700'
	);
};


BI.refresh = function(obj, url) {
	
	var div = BI.findCanvas( obj ); 	
	
	var o = new XMLHttpRequest();	
	o.open('GET', BI.addParam(url, 'noheader', ''), true);
	o.onreadystatechange = function() {
		if (o.readyState == 4) {
			div.innerHTML = o.responseText;
			
			// scroll if needed
			var divW = div.offsetWidth;
			var divH = div.offsetHeight;
			
			var win = jrapid.wrap( div ).getContainer().node;
			if (win && win.getBoundingClientRect) {
				// if we are inside a jrapid-window, use scroll bars
				var availableH = document.documentElement.clientHeight - (win.getBoundingClientRect().top + 50);
				var availableW = document.documentElement.clientWidth - (win.getBoundingClientRect().left + 10);
				
				if (divH > availableH) { 
					div.parentNode.style.overflowY = 'scroll'; 
					div.parentNode.style.height = availableH + 'px';
				}
				if (divW > availableW) { 
					div.parentNode.style.overflowX = 'scroll'; 
					div.parentNode.style.width = availableW + 'px';
				}
				// TODO: otherwise, remove scrolls?
			}
			
		}
	};
	o.send('');
};





// params manipulation

BI.removeParam = function(url, param) {
	var parts = url.split('?');
	if (parts.length == 1) {
		return url;
	}
	url = parts[0] + '?';
	var params = parts[1].split('&');
	for (var i=0; i < params.length; i++) {
		var keyValue = params[i].split('=');
		if (keyValue[0] != param) {
			url += '&' + params[i];
		}
	}		
	return url;
};

BI.addParam = function(url, param, value) {
	var url = BI.removeParam(url, param);
	return url + (url.indexOf('?') == -1 ? '?' : '&') + param + '=' + value;
};

// returns an array holding the values of the "param" parameter in the URL
BI.paramValues = function(url, param) {
	var parts = url.split('?');
	if (parts.length == 1) {
		return [];
	}
	var params = parts[1].split('&');
	for (var i=0; i < params.length; i++) {
		var keyValue = params[i].split('=');
		if (keyValue[0] == param) {
			return keyValue.length == 0 ? [] : keyValue[1].split(',');
		}
	}
	//return url;
	return [];
};






BI.chart = function(obj, foo, type) {
	if (type) {
		//var url = obj.parentNode.parentNode.parentNode.parentNode.getElementsByTagName('table')[0].parentNode.getAttribute('url');		
		var url = BI.findCanvasDivUrl( obj );
		obj.options[0].selected = true;
		BI.openImage( BI.addParam(url, 'chart', type), null, type );
	}
};

BI.showFilters = function(button) {
	// toggle
	button.parentNode.nextSibling.style.display = button.parentNode.nextSibling.style.display == '' ? 'none' : '';
};

BI.showFilter = function(obj, index) {
	var divs = obj.parentNode.nextSibling.childNodes;
	for (var i=0; i < divs.length; i++) {
		divs[i].style.display = i == index ? '' : 'none';
	}	
};

BI.measure = function(obj, url) {
	BI.refresh(
		obj, 
		BI.addParam(
			BI.removeParam( BI.removeParam(url, 'measure'), 'conf'), 
			'measure', 
			obj.value
		)
	);	
};

BI.refreshFilters = function(button, url, field) {
	var select = button.parentNode.parentNode.childNodes[0].firstChild; 
	var ids = "-1";
	for (var i=0; i < select.options.length; i++) { 
		ids += "," + select.options[i].value; 
	}
	url = BI.removeParam(url, 'conf');
	url = BI.removeParam(url, 'filter' + field);	
	if (select.options.length == 0) {
		BI.refresh(button, url);
	} else {
		BI.refresh(button, BI.addParam(url, 'filter' + field, ids));
	}
};

BI.refreshDimensions = function(button, url) {

	var select = button.parentNode.parentNode.childNodes[1].firstChild;
	var rows = "";
	for (var i=0; i < select.options.length; i++) { 
		rows += (i == 0 ? "" : ",") + select.options[i].value; 
	}
	select = button.parentNode.parentNode.childNodes[4].firstChild;
	var columns = "";
	for (var i=0; i < select.options.length; i++) { 
		columns += (i == 0 ? "" : ",") + select.options[i].value; 
	}
	
	url = BI.addParam(url, 'rows', rows);
	url = BI.addParam(url, 'columns', columns);
	url = BI.removeParam(url, 'conf');
	
	BI.refresh(button, url);
};

BI.reportAction = function(obj, id, url) {
	var c = document.getElementById('reportCanvas');
	c.style.padding = '10px';
	BI.include(BI.removeParam(url, 'conf'), c);
};


BI.resizeDashboard = function(obj) {
	var i = obj.children[0].selectedIndex + 1;
	var height = obj.getBoundingClientRect().bottom - obj.getBoundingClientRect().top;
	var h = (height - 20) / 2;
	obj.style.overflow = 'hidden';
	var tbody = obj.children[i].children[0];
	BI.resizeDashboardImg(tbody, 0, 0, h);
	BI.resizeDashboardImg(tbody, 0, 1, h);
	BI.resizeDashboardImg(tbody, 1, 0, h);
	BI.resizeDashboardImg(tbody, 1, 1, h);
};

BI.resizeDashboardImg = function(tbody, x, y, h) {
	var img = tbody.children[x].children[y].children[0];
	if (!parseInt(img.offsetWidth)) 
		return;
	if (!img.basesrc) { 
		img.basesrc = BI.removeParam(BI.removeParam(img.src, 'width'), 'height');
	}
	img.src = img.basesrc + '&width=' + parseInt(img.offsetWidth) + '&height=' + parseInt(h);
	img.style.height = h + 'px';
};

BI.selectDashboard = function(obj) {
	for (var i=1, c=obj.parentNode.children, n=c.length; i < n; i++) {
		c[i].style.display = obj.selectedIndex == (i-1) ? '' : 'none';
	}
	BI.resizeDashboard(obj.parentNode);
};





// returns the URL of the DIV element inside the CANVAS
BI.findCanvasDivUrl = function( node ){
	var canvas = BI.findCanvas( node );
	if (!canvas) {
		return "";
	}
	
	var url = canvas.children ?
			canvas.children[0].getAttribute( "url" ) :
			null;
	if (url) { 
		return url;
	} else {
		//canvas located, but no url
		alert( "Could not locate URL" );
	} 
};

// returns the CANVAS, given any element inside the CONTAINER
BI.findCanvas = function( node ){
	var canvas = null;
	
	while (node) {
		if (node.id == 'canvas') {
			canvas = node;
			break;
		}
		if (node.id == 'container') {
			canvas = node.children[ node.children.length-1 ];
			break;
		}
		node = node.parentNode;
	}
	if (!canvas) {
		alert( "ERROR: could not locate 'canvas' element" );
	}
	
	return canvas;
}

